<template>
  <el-dialog v-model="dialogVisible" width="60%" :close-on-click-modal="false" :close-on-press-escape="false" draggable
    destroy-on-close class="edit-dialog" @close="handleClose">
    <template #header>
      <div class="custom-dialog-header">
        <div class="header-title">
          <span class="title-text">{{ isNew ? '创建拦截规则' : '编辑拦截规则' }}</span>
        </div>
        <div class="request-info-bar">
          <div class="method-tag" :class="`method-${(method || 'GET').toLowerCase()}`">
            {{ method || 'GET' }}
          </div>
          <div class="url-display">
            <span class="url-label">URL:</span>
            <span class="url-value" :title="normalizeUrlToRelative(url)">
              {{ normalizeUrlToRelative(url) || '未知URL' }}
            </span>
          </div>
        </div>
      </div>
    </template>
    <div class="editor-content">
      <el-tabs v-model="activeTab" type="card" class="editor-tabs">
        <el-tab-pane name="params">
          <template #label>
            <div class="tab-label">
              <el-icon>
                <Setting />
              </el-icon>
              <span>请求参数</span>
            </div>
          </template>

          <div class="tab-content-wrapper">
            <div class="params-section">
              <div class="section-header">
                <h4 class="section-title">🔗 URL参数</h4>
              </div>
              <SimpleCodeEditor v-model="urlParamsJson" language="json" style="height: 200px" />
            </div>

            <el-divider />
            <div class="params-section">
              <div class="section-header">
                <h4 class="section-title">📋 请求头</h4>
                <div class="section-tip">
                  💡 提示：这里显示的是捕获到的请求头。浏览器自动添加的请求头（如Accept、Cookie等）需要手动添加。
                  您可以从开发者工具的Network面板复制完整的请求头。
                </div>
              </div>
              <SimpleCodeEditor v-model="requestHeadersJson" language="json" style="height: 400px" />
            </div>

            <!-- POST请求体参数 -->
            <el-divider v-if="isPostMethod" />
            <div v-if="isPostMethod" class="params-section">
              <div class="section-header">
                <h4 class="section-title">📝 请求体参数 (POST/PUT/PATCH)</h4>
              </div>
              <SimpleCodeEditor v-model="requestBodyJson" language="json" style="height: 200px" />
            </div>
          </div>
        </el-tab-pane>

        <el-tab-pane name="response">
          <template #label>
            <div class="tab-label">
              <el-icon>
                <Document />
              </el-icon>
              <span>响应数据</span>
            </div>
          </template>

          <div class="tab-content-wrapper">
            <div class="params-section">
              <div class="section-header">
                <h4 class="section-title">📄 响应数据</h4>
              </div>
              <SimpleCodeEditor v-model="responseDataJson" language="json" style="height: 400px" />
            </div>
          </div>
        </el-tab-pane>

        <el-tab-pane name="preview">
          <template #label>
            <div class="tab-label">
              <el-icon>
                <View />
              </el-icon>
              <span>预览</span>
            </div>
          </template>

          <div class="tab-content-wrapper">
            <div class="preview-container">
              <!-- URL参数预览 -->
              <div class="preview-item">
                <div class="preview-header">
                  <el-icon class="preview-icon">
                    <Link />
                  </el-icon>
                  <span class="preview-title">URL 查询参数</span>
                  <div class="preview-badge" v-if="formattedUrlParams">有数据</div>
                  <div class="preview-badge empty" v-else>无数据</div>
                </div>
                <div class="preview-body">
                  <pre v-if="formattedUrlParams" class="preview-json">{{ formattedUrlParams }}</pre>
                  <div v-else class="empty-preview">暂无URL参数</div>
                </div>
              </div>

              <!-- 响应数据预览 -->
              <div class="preview-item">
                <div class="preview-header">
                  <el-icon class="preview-icon">
                    <Document />
                  </el-icon>
                  <span class="preview-title">响应数据内容</span>
                  <div class="preview-badge">有数据</div>
                </div>
                <div class="preview-body">
                  <pre class="preview-json">{{ formattedResponseData }}</pre>
                </div>
              </div>

              <!-- 请求头预览 -->
              <div class="preview-item">
                <div class="preview-header">
                  <el-icon class="preview-icon">
                    <Setting />
                  </el-icon>
                  <span class="preview-title">HTTP 请求头</span>
                  <div class="preview-badge" v-if="formattedRequestHeaders">有数据</div>
                  <div class="preview-badge empty" v-else>无数据</div>
                </div>
                <div class="preview-body">
                  <pre v-if="formattedRequestHeaders" class="preview-json">{{ formattedRequestHeaders }}</pre>
                  <div v-else class="empty-preview">暂无请求头</div>
                </div>
              </div>

              <!-- 请求体参数预览 (仅POST/PUT/PATCH) -->
              <div v-if="isPostMethod" class="preview-item">
                <div class="preview-header">
                  <el-icon class="preview-icon">
                    <Document />
                  </el-icon>
                  <span class="preview-title">请求体参数</span>
                  <div class="preview-badge" v-if="formattedRequestBody">有数据</div>
                  <div class="preview-badge empty" v-else>无数据</div>
                </div>
                <div class="preview-body">
                  <pre v-if="formattedRequestBody" class="preview-json">{{ formattedRequestBody }}</pre>
                  <div v-else class="empty-preview">暂无请求体参数</div>
                </div>
              </div>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose">取消</el-button>
        <el-button type="primary" @click="save" :loading="saving">
          {{ isNew ? '创建拦截' : '保存修改' }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import SimpleCodeEditor from './SimpleCodeEditor.vue'
import { Setting, Document, View, Link } from '@element-plus/icons-vue'

const props = defineProps({
  visible: Boolean,
  url: String,
  method: String,
  responseData: String,
  isNew: Boolean,
  itemId: Number,
  existingParams: Object,
})

const emit = defineEmits(['close', 'save'])

const dialogVisible = ref(false)
const activeTab = ref('params')
const responseDataJson = ref('')
const urlParamsJson = ref('')
const requestHeadersJson = ref('')
const requestBodyJson = ref('')
const saving = ref(false)

// 判断是否为POST类型的请求
const isPostMethod = computed(() => {
  const method = (props.method || 'GET').toUpperCase()
  return ['POST', 'PUT', 'PATCH'].includes(method)
})

// 计算最终URL
const finalUrl = computed(() => {
  // 添加保护性检查
  if (!props.url) {
    console.warn('props.url is undefined')
    return ''
  }

  // 规范化为相对路径
  const normalizedBaseUrl = normalizeUrlToRelative(props.url)

  if (!urlParamsJson.value || urlParamsJson.value.trim() === '')
    return normalizedBaseUrl

  try {
    const params = JSON.parse(urlParamsJson.value)
    if (!params || Object.keys(params).length === 0) return normalizedBaseUrl

    const url = new URL(normalizedBaseUrl, window.location.origin)
    url.search = '' // 清空现有参数

    Object.entries(params).forEach(([key, value]) => {
      if (key && value !== null && value !== undefined) {
        url.searchParams.set(key, String(value))
      }
    })

    // 返回相对路径格式
    return url.pathname + url.search
  } catch (error) {
    console.error('URL计算错误:', error)
    return normalizedBaseUrl
  }
})

// 格式化响应数据用于预览
const formattedResponseData = computed(() => {
  try {
    const parsed = JSON.parse(responseDataJson.value)
    return JSON.stringify(parsed, null, 2)
  } catch (error) {
    return responseDataJson.value
  }
})

// 格式化URL参数用于预览
const formattedUrlParams = computed(() => {
  try {
    if (urlParamsJson.value && urlParamsJson.value.trim()) {
      const urlParams = JSON.parse(urlParamsJson.value)
      if (Object.keys(urlParams).length > 0) {
        return JSON.stringify(urlParams, null, 2)
      }
    }
  } catch (error) {
    // 忽略JSON解析错误
  }
  return null
})

// 格式化请求头用于预览
const formattedRequestHeaders = computed(() => {
  try {
    if (requestHeadersJson.value && requestHeadersJson.value.trim()) {
      const requestHeaders = JSON.parse(requestHeadersJson.value)
      if (Object.keys(requestHeaders).length > 0) {
        return JSON.stringify(requestHeaders, null, 2)
      }
    }
  } catch (error) {
    // 忽略JSON解析错误
  }
  return null
})

// 格式化请求体参数用于预览
const formattedRequestBody = computed(() => {
  try {
    if (requestBodyJson.value && requestBodyJson.value.trim()) {
      const requestBody = JSON.parse(requestBodyJson.value)
      if (typeof requestBody === 'object' && requestBody !== null && Object.keys(requestBody).length > 0) {
        return JSON.stringify(requestBody, null, 2)
      } else if (typeof requestBody === 'string' && requestBody.length > 0) {
        return requestBody
      }
    }
  } catch (error) {
    // 如果不是JSON，直接返回原始字符串
    if (requestBodyJson.value && requestBodyJson.value.trim()) {
      return requestBodyJson.value.trim()
    }
  }
  return null
})

// URL规范化函数 - 转换为相对路径格式
const normalizeUrlToRelative = (url) => {
  try {
    if (!url) return ''

    // 如果已经是相对路径，直接返回
    if (url.startsWith('/')) {
      return url
    }

    // 如果是完整URL，提取路径和参数部分
    if (url.startsWith('http')) {
      const urlObj = new URL(url)
      return urlObj.pathname + urlObj.search
    }

    // 其他情况直接返回
    return url
  } catch (error) {
    console.warn('URL规范化失败:', error, 'URL:', url)
    return url || ''
  }
}

// 初始化数据
const initializeData = () => {
  // 初始化响应数据
  try {
    if (props.responseData) {
      const parsed = JSON.parse(props.responseData)
      responseDataJson.value = JSON.stringify(parsed, null, 2)
    } else {
      responseDataJson.value = JSON.stringify(
        { message: '请输入有效的JSON数据' },
        null,
        2
      )
    }
  } catch (error) {
    responseDataJson.value = JSON.stringify(
      { message: props.responseData || '请输入有效的JSON数据' },
      null,
      2
    )
  }

  // 解析URL参数
  urlParamsJson.value = '{}'
  if (props.url) {
    try {
      // 规范化URL为相对路径格式
      const normalizedUrl = normalizeUrlToRelative(props.url)
      const url = new URL(normalizedUrl, window.location.origin)
      const params = {}
      url.searchParams.forEach((value, key) => {
        params[key] = value
      })
      urlParamsJson.value = JSON.stringify(params, null, 2)
    } catch (error) {
      console.warn('解析URL参数失败:', error)
      urlParamsJson.value = '{}'
    }
  }

  // 初始化请求头 - 显示捕获的数据，并提供常见请求头的提示
  if (props.existingParams?.requestHeaders && Object.keys(props.existingParams.requestHeaders).length > 0) {
    // 显示捕获的请求头
    requestHeadersJson.value = JSON.stringify(
      props.existingParams.requestHeaders,
      null,
      2
    )
    console.log('🔍 EditDialog显示的请求头数据:', props.existingParams.requestHeaders);
  } else {
    // 如果没有现有数据，提供一个包含常见请求头的模板，用户可以根据需要修改
    const commonHeaders = {
      "Accept": "application/json, text/plain, */*",
      "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
      "Accept-Encoding": "gzip, deflate, br",
      "Content-Type": "application/json",
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
      "Referer": window.location.href,
      "Origin": window.location.origin,
      // 用户可以根据实际需要添加或删除
      "Authorization": "",
      "Cookie": "",
      "X-Requested-With": "XMLHttpRequest"
    }

    requestHeadersJson.value = JSON.stringify(commonHeaders, null, 2)
    console.log('🔍 EditDialog提供常见请求头模板');
  }

  // 初始化请求体参数（仅POST/PUT/PATCH请求）
  if (isPostMethod.value) {
    if (props.existingParams?.requestBody) {
      try {
        // 如果是对象，格式化为JSON
        if (typeof props.existingParams.requestBody === 'object') {
          requestBodyJson.value = JSON.stringify(props.existingParams.requestBody, null, 2)
        } else {
          // 如果是字符串，尝试解析为JSON再格式化
          const parsed = JSON.parse(props.existingParams.requestBody)
          requestBodyJson.value = JSON.stringify(parsed, null, 2)
        }
      } catch (error) {
        // 如果解析失败，直接使用原始字符串
        requestBodyJson.value = String(props.existingParams.requestBody)
      }
    } else {
      // 提供默认的请求体示例
      requestBodyJson.value = JSON.stringify(
        {
          "key1": "value1",
          "key2": "value2"
        },
        null,
        2
      )
    }
  } else {
    requestBodyJson.value = ''
  }
}

// 验证JSON格式的辅助函数
const validateJSONField = (value, fieldName, allowEmpty = false) => {
  console.log(`验证${fieldName}:`, value)

  if (!value || value.trim() === '') {
    console.log(`${fieldName}为空, allowEmpty:`, allowEmpty)
    if (allowEmpty) {
      return {}
    }
    throw new Error(`${fieldName}不能为空`)
  }

  try {
    const parsed = JSON.parse(value)
    console.log(`${fieldName}验证通过:`, parsed)
    return parsed
  } catch (error) {
    console.log(`${fieldName}JSON解析失败:`, error.message)
    throw new Error(`${fieldName}JSON格式错误: ${error.message}`)
  }
}

// 保存
const save = async () => {
  if (saving.value) return

  saving.value = true

  try {
    // 调试信息
    console.log('保存验证开始')
    console.log('响应数据值:', responseDataJson.value)
    console.log('URL参数值:', urlParamsJson.value)
    console.log('请求头值:', requestHeadersJson.value)

    // 1. 验证响应数据（必填）
    validateJSONField(responseDataJson.value, '响应数据')

    // 2. 验证URL参数（可以为空）
    const urlParams = validateJSONField(urlParamsJson.value, 'URL参数', true)

    // 3. 验证请求头（可以为空）
    const requestHeaders = validateJSONField(
      requestHeadersJson.value,
      '请求头',
      true
    )

    // 4. 验证请求体参数（仅POST/PUT/PATCH，可以为空）
    let requestBody = null
    if (isPostMethod.value) {
      requestBody = validateJSONField(
        requestBodyJson.value,
        '请求体参数',
        true
      )
    }

    // 发送保存事件，使用已验证的数据
    const saveData = {
      url: finalUrl.value || props.url || '',
      responseData: responseDataJson.value || '{}',
      editedParams: {
        urlParams: urlParams || {},
        requestHeaders: requestHeaders || {},
        requestBody: requestBody,
      },
    }

    console.log('准备发送保存数据:', saveData)
    emit('save', saveData)

    // 验证通过，直接发送保存事件，不显示多余提示
  } catch (error) {
    console.error('保存失败:', error)
    ElMessage.error(`保存失败: ${error.message}`)
    // 保存失败时保持对话框打开，让用户修改
  } finally {
    saving.value = false
  }
}

// 关闭
const handleClose = () => {
  if (saving.value) {
    ElMessage.warning('正在保存中，请稍候...')
    return
  }
  dialogVisible.value = false
  emit('close')
}

// 监听props变化
watch(
  () => props.visible,
  (newVal) => {
    dialogVisible.value = newVal
    if (newVal) {
      initializeData()
      activeTab.value = 'params'
    }
  }
)

onMounted(() => {
  dialogVisible.value = props.visible
  if (props.visible) {
    initializeData()
  }
})
</script>

<style scoped>
/* 自定义对话框头部样式 */
.custom-dialog-header {
  padding: 0;
  margin: 0;
}

.header-title {
  margin-bottom: 16px;
}

.title-text {
  font-size: 20px;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.request-info-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 6px 6px;
  background: rgba(255, 255, 255, 0.15);
  border-radius: 8px;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.method-tag {
  padding: 6px 12px;
  border-radius: 10px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: white;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  min-width: 50px;
  text-align: center;
}

.method-get {
  background: linear-gradient(135deg, #4ade80, #22c55e);
}

.method-post {
  background: linear-gradient(135deg, #60a5fa, #3b82f6);
}

.method-put {
  background: linear-gradient(135deg, #fbbf24, #f59e0b);
}

.method-delete {
  background: linear-gradient(135deg, #f87171, #ef4444);
}

.method-patch {
  background: linear-gradient(135deg, #a78bfa, #8b5cf6);
}

.url-display {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}

.url-label {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

.url-value {
  font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 13px;
  background: rgba(255, 255, 255, 0.1);
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  backdrop-filter: blur(5px);
}

/* 现代化的编辑器样式 */
.edit-dialog {
  --el-dialog-width: 80%;
  --el-dialog-margin-top: 3vh;
}

/* 覆盖Element Plus的默认样式 */
.edit-dialog :deep(.el-dialog) {
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
  max-height: 90vh;
  overflow: hidden;
}

.edit-dialog :deep(.el-dialog__header) {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 24px 28px 28px 28px;
  margin: 0;
  border-radius: 12px 12px 0 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.edit-dialog :deep(.el-dialog__title) {
  color: white;
  font-size: 18px;
  font-weight: 600;
}

.edit-dialog :deep(.el-dialog__headerbtn .el-dialog__close) {
  color: white;
  font-size: 20px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  transition: all 0.3s;
}

.edit-dialog :deep(.el-dialog__headerbtn .el-dialog__close:hover) {
  background: rgba(255, 255, 255, 0.2);
  transform: scale(1.1);
}

.edit-dialog :deep(.el-dialog__body) {
  padding: 0;
  height: 55vh;
  /* 降低高度 */
  overflow: hidden;
}

.edit-dialog :deep(.el-dialog__footer) {
  background: #f8f9fa;
  border-top: 1px solid #e9ecef;
  padding: 16px 24px;
  border-radius: 0 0 12px 12px;
}

.dialog-header-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.dialog-title {
  font-size: 18px;
  font-weight: 600;
  color: white;
  display: flex;
  align-items: center;
  gap: 8px;
}

.dialog-url {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.9);
  word-break: break-all;
  background: rgba(255, 255, 255, 0.15);
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
}

.editor-content {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.editor-tabs {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.editor-tabs :deep(.el-tabs__header) {
  background: #f8f9fa;
  margin: 0;
  padding: 0 20px;
  border-bottom: 1px solid #e9ecef;
}

.editor-tabs :deep(.el-tabs__nav-wrap) {
  background: transparent;
}

.editor-tabs :deep(.el-tabs__item) {
  color: #6c757d;
  font-size: 14px;
  font-weight: 500;
  padding: 16px 20px;
  border: none;
  border-radius: 8px 8px 0 0;
  margin-right: 4px;
  transition: all 0.3s;
}

.editor-tabs :deep(.el-tabs__item:hover) {
  background: #e9ecef;
  color: #495057;
}

.editor-tabs :deep(.el-tabs__item.is-active) {
  color: #667eea;
  background: white;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
}

.editor-tabs :deep(.el-tabs__content) {
  flex: 1;
  padding: 0;
  overflow: hidden;
}

.editor-tabs :deep(.el-tab-pane) {
  height: 100%;
}

.tab-label {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tab-content-wrapper {
  height: 100%;
  padding: 24px;
  overflow-y: auto;
}

.params-section {
  margin-bottom: 32px;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.section-title {
  font-weight: 600;
  color: #2c3e50;
  font-size: 16px;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-tip {
  margin-top: 8px;
  padding: 8px 12px;
  background: #f0f9ff;
  border: 1px solid #bae6fd;
  border-radius: 4px;
  font-size: 12px;
  color: #0369a1;
  line-height: 1.4;
}

.params-group {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.no-params {
  text-align: center;
  padding: 40px 20px;
}

.param-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 12px;
  border: 1px solid #e9ecef;
  transition: all 0.3s;
}

.param-item:hover {
  background: #e9ecef;
  border-color: #667eea;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
}

.param-key {
  width: 200px;
}

.param-value {
  flex: 1;
}

.preview-container {
  padding: 0;
  height: 100%;
}

.preview-section {
  height: 100%;
}

.preview-section :deep(.el-card) {
  height: 100%;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.preview-section :deep(.el-card__header) {
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  border-bottom: 1px solid #e9ecef;
  font-weight: 600;
  color: #2c3e50;
  font-size: 14px;
  padding: 16px 20px;
}

.preview-section :deep(.el-card__body) {
  padding: 20px;
  height: calc(100% - 60px);
  overflow-y: auto;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 8px;
}

.preview-content {
  height: 100%;
}

.preview-item {
  margin-bottom: 16px;
}

.preview-item h5 {
  margin: 16px 0 8px 0;
  color: #2c3e50;
  font-size: 14px;
  font-weight: 600;
}

.params-preview-json {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.6;
  overflow-x: auto;
  max-height: 400px;
  overflow-y: auto;
  border: 1px solid #e9ecef;
  white-space: pre-wrap;
  word-break: break-all;
  margin: 0;
  color: #2c3e50;
}



/* 预览容器 */
.preview-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 20px;
}

/* 预览项目 */
.preview-item {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  overflow: hidden;
  transition: all 0.3s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.preview-item:hover {
  border-color: #3b82f6;
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
}

/* 预览头部 */
.preview-header {
  display: flex;
  align-items: center;
  padding: 16px 20px;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-bottom: 1px solid #e5e7eb;
  gap: 12px;
}

.preview-icon {
  font-size: 18px;
  color: #3b82f6;
}

.preview-title {
  font-size: 15px;
  font-weight: 600;
  color: #1f2937;
  flex: 1;
}

.preview-badge {
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  background: #10b981;
  color: white;
}

.preview-badge.empty {
  background: #6b7280;
}

/* 预览内容 */
.preview-body {
  padding: 20px;
}

.preview-json {
  background: #1e293b;
  color: #e2e8f0;
  padding: 20px;
  border-radius: 8px;
  font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.6;
  overflow-x: auto;
  max-height: 200px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
  margin: 0;
  border: 1px solid #334155;
}

.empty-preview {
  text-align: center;
  color: #9ca3af;
  font-style: italic;
  padding: 40px 20px;
  font-size: 14px;
  background: #f9fafb;
  border-radius: 8px;
  border: 2px dashed #d1d5db;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 16px;
}

.dialog-footer .el-button {
  padding: 12px 24px;
  font-weight: 500;
  border-radius: 8px;
}

/* JSON文本框样式 */
.json-textarea :deep(.el-textarea__inner) {
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.5;
  background: #1e1e1e;
  color: #d4d4d4;
  border: 1px solid #404040;
  border-radius: 6px;
  resize: vertical;
}

.json-textarea :deep(.el-textarea__inner:focus) {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.json-textarea :deep(.el-textarea__inner::placeholder) {
  color: #858585;
}
</style>
